package com.weilan.ark3.tcp;

import com.weilan.ark3.service.ModbusConfService;
import com.weilan.ark3.utils.ComFault;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;

import static com.weilan.ark3.buffer.OverallSituation.tcpMasterStartId;
import static com.weilan.ark3.buffer.OverallSituation.ucStartId;

/**
 * modbus主站
 *
 * @author 徐阿东
 * @date 2023/5/31 14:25
 */
@Slf4j
@Component
public class TcpMaster {
    @Autowired
    private ModbusConfService modbusConfService;

    public static HashMap<Integer, ModbusMaster> masterMap = new HashMap<>();

    // 允许读取的最大长度
    private final static int READ_MAX = 100;

    /**
     * }
     */
    public static void init(int number) {//配置几台柜子
        try {
            ModbusFactory modbusFactory = new ModbusFactory();
            for (int i = tcpMasterStartId, j = ucStartId; i < tcpMasterStartId + number; i++, j++) {
                IpParameters params = new IpParameters();
                params.setHost("192.168.1." + i); // 设置Modbus从站的IP地址
                params.setPort(502); // 设置Modbus从站的端口号
                ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false);
                tcpMaster.setRetries(1);
                tcpMaster.setTimeout(500);
                masterMap.put(j, tcpMaster);
                log.info("TCP主站192.168.1.{}创建成功", i);
            }
        } catch (Exception e) {
            log.error("TCP主站创建失败:{}", e.getMessage());
        }
    }

    /**
     * 连续读取tcp数据
     *
     * @param slaveId 从站地址
     * @param start   起始地址的偏移量
     * @param len     待读寄存器的个数
     */
    public short[] continueReadData(int slaveId, int start, int len, HashMap<Integer, ModbusMaster> map) {
        ModbusMaster master = map.get(slaveId);
        short[] resultArr = new short[len];
        int times = len / READ_MAX;
        int surplus = len % READ_MAX;
        try {
            for (int i = 0; i <= times; i++) {
                int realLen = i != times ? READ_MAX : surplus;
                if (i == times && surplus == 0) break;
                ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start + i * READ_MAX, realLen);
                ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
                short[] onceData = response.getShortData();
                System.arraycopy(onceData, 0, resultArr, i * READ_MAX, realLen);
            }
            ComFault.CommunicationReserve(slaveId);
            modbusConfService.writerToEMS();
            return resultArr;
        } catch (Exception e) {
            log.error(slaveId + "TCP从站读取异常:{}", e.getMessage());
            ComFault.CommunicationInterrupt(slaveId);
            modbusConfService.writerToEMS();
            return null;
        }

    }

}
